using Wpf.Ui.Controls;

namespace FileTransferDesktop.Helpers;

/// <summary>
/// Attached property helper for PasswordBox to enable two-way data binding
/// </summary>
public static class PasswordBoxHelper
{
    // Attached property for binding the password
    public static readonly DependencyProperty BoundPasswordProperty =
        DependencyProperty.RegisterAttached(
            "BoundPassword",
            typeof(string),
            typeof(PasswordBoxHelper),
            new FrameworkPropertyMetadata(
                string.Empty,
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                OnBoundPasswordChanged
            )
        );

    // Attached property to track if we're updating internally (to prevent infinite loops)
    public static readonly DependencyProperty UpdatingPasswordProperty =
        DependencyProperty.RegisterAttached(
            "UpdatingPassword",
            typeof(bool),
            typeof(PasswordBoxHelper)
        ); // Attached property to track if we've attached to the password box
    public static readonly DependencyProperty AttachedProperty =
        DependencyProperty.RegisterAttached(
            "Attached",
            typeof(bool),
            typeof(PasswordBoxHelper),
            new PropertyMetadata(false, OnAttachedChanged)
        );

    public static string GetBoundPassword(DependencyObject obj)
    {
        return (string)obj.GetValue(BoundPasswordProperty);
    }

    public static void SetBoundPassword(DependencyObject obj, string value)
    {
        obj.SetValue(BoundPasswordProperty, value);
    }

    public static bool GetUpdatingPassword(DependencyObject obj)
    {
        return (bool)obj.GetValue(UpdatingPasswordProperty);
    }

    public static void SetUpdatingPassword(DependencyObject obj, bool value)
    {
        obj.SetValue(UpdatingPasswordProperty, value);
    }

    public static bool GetAttached(DependencyObject obj)
    {
        return (bool)obj.GetValue(AttachedProperty);
    }

    public static void SetAttached(DependencyObject obj, bool value)
    {
        obj.SetValue(AttachedProperty, value);
    }

    private static void OnAttachedChanged(
        DependencyObject obj,
        DependencyPropertyChangedEventArgs e
    )
    {
        if (obj is PasswordBox passwordBox)
        {
            if ((bool)e.NewValue)
            {
                passwordBox.PasswordChanged += OnPasswordChanged;
            }
            else
            {
                passwordBox.PasswordChanged -= OnPasswordChanged;
            }
        }
    }

    private static void OnBoundPasswordChanged(
        DependencyObject obj,
        DependencyPropertyChangedEventArgs e
    )
    {
        if (obj is PasswordBox passwordBox)
        {
            // Ensure we're attached to the password box
            if (!GetAttached(passwordBox))
            {
                SetAttached(passwordBox, true);
            }

            var newPassword = (string)e.NewValue;
            if (!GetUpdatingPassword(passwordBox))
            {
                passwordBox.Password = newPassword ?? string.Empty;
            }
        }
    }

    private static void OnPasswordChanged(object sender, RoutedEventArgs e)
    {
        if (sender is PasswordBox passwordBox)
        {
            SetUpdatingPassword(passwordBox, true);
            SetBoundPassword(passwordBox, passwordBox.Password);
            SetUpdatingPassword(passwordBox, false);
        }
    }
}
